<?php


namespace app\community\oauth2\Entities;

use app\community\oauth2\Exception\ClientNotFoundException;
use app\community\oauth2\Exception\ClientUserInvalidException;
use app\community\oauth2\Model\oauthClientModel;
use app\community\oauth2\Entities\ClientEntity;
use app\community\oauth2\Model\oauthUserUnionClientModel;
use League\OAuth2\Server\Entities\UserEntityInterface;


class UserEntity implements UserEntityInterface
{

    protected array $userInfo = [];
    protected ClientEntity $clientEntity;

    /**
     * 获取当前 需要授权的用户 ID/OPENID
     * @return int|string
     * @throws ClientNotFoundException
     */
    public function getIdentifier(): int|string
    {
        // TODO: Implement getIdentifier() method.
        $id = $this->userInfo['uid'] ?? request() -> params('open_id');
        if (!$id) throw new ClientNotFoundException('Missing required parameters open_id', 403);
        if (empty($this->userInfo['uid'])) {
            $this->validIdentifier($id, request() -> params('client_id'));
        }
        $this->userInfo['uid'] = $id;
        return $id;
    }

    /**
     * 验证 当前账户是否有效
     * @param string $id
     * @param string $app_id 应用ID
     * @return array
     * @throws ClientNotFoundException
     */
    public function validIdentifier(string $id = '', string $app_id = ''): array
    {
        $id = $id ?: $this->getIdentifier();
        $info = (new oauthUserUnionClientModel()) -> findInfo([
            'app_id' => $app_id ?: $this->clientEntity -> getIdentifier(),
            'openid' => $id
        ]);
        if (!$info) {
            throw new ClientNotFoundException('invalid open_id', 403);
        }
        return $info;
    }

    /**
     * 密码登录授权调用
     * @param string $userName
     * @param string $passWord
     * @param ClientEntity $clientEntity
     * @return $this
     * @throws ClientUserInvalidException
     */
    public function userLogin(string $userName, string $passWord, ClientEntity $clientEntity): static
    {
        $this -> clientEntity = $clientEntity;

        $userInfo = (new oauthClientModel())
            -> getUnionUserInfoByUserName(
                $userName,
                $this->clientEntity -> getIdentifier(),
                $this->clientEntity -> getClientSecret()
            );

        // 验证账户是否存在
        if ($userInfo -> isEmpty()) {
            throw new ClientUserInvalidException('账户不存在', 403);
        }

        // 验证密码
        if (!password_verify($passWord, $userInfo -> getData('password'))) {
            throw new ClientUserInvalidException('账户密码错误', 403);
        }

        $this->userInfo = $userInfo -> toArray();
        return $this;
    }
}